#ifndef _PHY_H
#define _PHY_H


#define INIT_CRC8		0x0
#define POLYNOMIAL8		0x07


//----------------------------------------------------------------------------
//                      Prime PPDU Header
//----------------------------------------------------------------------------

#define PRIME_PRCL_DBPSK           0     // DBPSK w/o FEC
#define PRIME_PRCL_DQPSK           1     // DQPSK w/o FEC 
#define PRIME_PRCL_D8PSK           2     // D8PSK w/o FEC
#define PRIME_PRCL_RSVD            3     // Reserved

#define PRIME_PRCL_DBPSK_F         4     // DBPSK w/ FEC  
#define PRIME_PRCL_DQPSK_F         5     // DQPSK w/ FEC  
#define PRIME_PRCL_D8PSK_F         6     // D8PSK w/ FEC  

#define PRIME_PRCL_ROBO_4          8     // DBPSK w/ FEC + 1/4
#define PRIME_PRCL_ROBO_8         12     // DBPSK w/ FEC + 1/8


typedef enum
{
	PRIME_STAT_SUCCESS          = 0,
	PRIME_STAT_ERROR            = 1,
	PRIME_STAT_SYNC_FOUND       = 2,
	PRIME_STAT_SYNC_VERIFIED    = 3,
	PRIME_STAT_SYNC_NONE        = 4
} PRIME_status_t;


/* PHY status */
typedef enum
{
	PHY_STAT_SUCCESS                = 0,
	PHY_STAT_FAILURE                = 1,
	PHY_STAT_PREAMBLE_NOT_DETECTED  = 2,
	PHY_STAT_HEADER_CRC_FAILED      = 3,
	PHY_STAT_PAYLOAD_CRC_FAILED     = 4,
	PHY_STAT_ILLEGAL_PARAMETERS     = 5,
	PHY_STAT_ILLEGAL_OPERATIONS     = 6,
	PHY_STAT_UNKNOWN_ID             = 7,
	PHY_STAT_TX_LATE                = 8,
	PHY_STAT_INVALID_LEN            = 9,
	PHY_STAT_INVALID_SCH            = 10,
	PHY_STAT_INVALID_LEV            = 11,
	PHY_STAT_BUF_OVRUN              = 12,
	PHY_STAT_BUSY                   = 13,
	PHY_STAT_CMD_IN_PLACE           = 14,
	PHY_STAT_NOT_IN_SYNC            = 15,
	PHY_STAT_RX_BUF_OVERRUN         = 16
}PHY_status_t;


typedef PRIME_status_t (*FSM_action_t)(void* data_p);

/* Action cell */
typedef  struct
{
	UINT16                nextState;      /* next state */
	FSM_action_t          actionFunc_p;   /**< action function */
}FSM_actionCell_t;

/* Matrix type */
typedef FSM_actionCell_t*       FSM_matrix_t;

/* State transition function */
typedef PRIME_status_t (*FSM_eventActivation_t)(UINT16 currState_p, UINT16 event, void* data_p);

/* Action function type definition */

/* General FSM structure */
typedef struct
{
	const FSM_actionCell_t  *stateEventMatrix; /* State and Event matrix */
	UINT16                  maxStates;        /* Max Number of states in the matrix */
	UINT16                  maxEvents;        /* Max Number of events in the matrix */
	UINT16                  previousState;    /* Previous state */
	UINT16                  currentState;     /* Current state */
	FSM_eventActivation_t   transitionFunc_p; /* State transition function */

}FSM_stateMachine_t;

typedef struct 
{
    SINT16 *ipcbptr;        // input buffer pointer
    SINT16 *tfptr;          // twiddle factor table pointer
    SINT16 size;
    SINT16 nrstage;
    SINT16 step;
    void (*init)(void *);
    void (*calc)(void *);
}PHY_cfft16_t;

/* FIR filter structure */
typedef struct
{
	const SINT16 *coeff_p;      // pointer to FIR coeffs
	UINT16 nTaps;         	// Number of FIR taps
}PHY_fir_t;

typedef struct 
{
	UINT16 delay[6];  // delay line
	UINT16 *u_p;                          // pointer to uncoded bits buffer
	UINT16 *c_p;                          // pointer to coded bits buffer
	UINT16 nBits;                         // Number of uncoded bits

}PHY_cnvEnc_t; 

/* PHY callback events */
typedef enum
{
	PHY_EV_RX_START_DONE        = 0,
	PHY_EV_TX_PPDU_DONE         = 1,
	PHY_EV_RX_PPDU_DONE         = 2,
	PHY_EV_TX_SUSPEND_DONE      = 3,
	PHY_EV_RX_SUSPEND_DONE      = 4,
	PHY_EV_TX_RESUME_DONE       = 5,
	PHY_EV_RX_RESUME_DONE       = 6,
	PHY_EV_TX_TESTMODE_DONE     = 7

}PHY_ev_t;

/* Tx PPDU done callback data structure */ 
typedef struct
{
	UINT32       ppduAddr;          // Tx PPDU address passed by caller

}PHY_cbTxPpdu_t;

/* Rx channel acquired callback data structure */ 
typedef struct
{
	SINT16       rssi;              // rssi in dBm
	UINT16       nSymbols;          // number of symbols for ppdu

}PHY_cbRxSync_t;

/* Rx PPDU callback data structure */ 
typedef struct
{
	UINT32       ppduInfoAddr;       // Rx PPDU info address (see PHY_rxPpdu_t in phy_rx.h)

}PHY_cbRxPpdu_t;

/* PHY callbacks data structure */
typedef struct
{
	PHY_status_t         status;     // callback status  
	union
	{
		PHY_cbTxPpdu_t     txPpdu;     // PHY Tx ppdu done callback
		PHY_cbRxSync_t     rxSync;     // PHY Rx channel acq callback
		PHY_cbRxPpdu_t     rxPpdu;     // PHY Rx ppdu callback

	}cbParms;

}PHY_cbData_t;

/* Callback functions */
typedef void (*PHY_cbFunc_t)(PHY_ev_t eventID, PHY_cbData_t *cbData_p);

typedef union
{
	SINT16 PHY_rxAfeInBuf[2240];
	SINT16 PHY_tx_outBuf[2][1128];
}PHY_afeBuf_t;

typedef struct
{
	Uint16 *pnScm_p; //pointer to the PN sequence for modulator; reload every PPDU
}PHY_scm_handle_t;

typedef struct
{
	Uint16 *pnMod_p; //pointer to the PN sequence for modulator; reload every PPDU
}PHY_mod_handle_t;

// Interlaver configuration parameters
typedef struct
{
	UINT16 nCols[4];       
	UINT16 nRows[4];

}PHY_intlv_t;

typedef struct
{
  UINT16 startIdx;
  UINT16 endIdx;
  UINT16 centerIdx;
  SINT32 delta;

  UINT16 numLoTones;
  UINT16 numHiTones;

  UINT16 loStartIdx;
}PHY_bandCfg_t;

/*********************************/
/* AAGC                          */
/*********************************/

typedef enum
{
	PHY_AAGC_STAGE_IACQ     = 0,
	PHY_AAGC_STAGE_STDY     = 1
}PHY_aagcStage_t;

typedef enum
{
	PHY_AAGC_NODE_0     = 0,   // reserved for base nodes
	PHY_AAGC_NODE_1     = 1,
	PHY_AAGC_NUM_NODES  = 2 // measurements of nodes that known.
                                
}PHY_aagcNode_t;

typedef enum
{
	PHY_AAGC_MODE_A = 0,
	PHY_AAGC_MODE_B = 1,
	PHY_AAGC_MODE_C = 2,
	PHY_AAGC_MODE_D = 3,

	PHY_AAGC_NUM_MODES = 4

}PHY_aagcMode_t;

/*****************************************************************************/
/* Data Structures                                                           */
/*****************************************************************************/
/* DAGC structure */
typedef struct
{
	SINT16 power_Q4dB;                  // power in dB (Q4)
	SINT16 hdRoom_Q4dB;                 // headroom in dB (Q4)
	SINT16 gain[2];    // linear gain - prv and current (Q0)

}PHY_dagc_t;


/* AAGC structure */
typedef struct
{
                       // all in Q0 for now, keep it @ Q4 if needed
	SINT16 totPower_dB;  // total power @ ADC output 
	SINT16 dsrPower_dB;  // desired power @ DFE output 
	SINT16 aciPower_dB;  // aci power (total - desired)

	SINT16 gainIdx;      // PGA gain setting idx

}PHY_aagcMeas_t;

typedef struct
{
	SINT16 mode;         // Alg A/B/C/D
	SINT16 tgtPower_dB;  // target power (ADC range - headroom )

	SINT16 tblkLen;      // number of samples to measure for total power
	SINT16 dblkLen;      // number of samples to measure for desired power

	SINT16 tShift;       // number of shifts for avg
	SINT16 dShift;       // number of shifts for avg

	SINT16 initGainIdx;  // gain idx for prmb detection
	SINT16 stdyGainIdx;  // gain idx for steady
	SINT16 currIdx;      // current measurement idx

	PHY_aagcMeas_t meas[2]; // number of current measures
										// whoever listening to

	PHY_aagcMeas_t measNodes[PHY_AAGC_NUM_NODES];  // nodes that are known 
											   // prv

}PHY_aagc_t;

typedef struct
{
	SINT16 tgtPower_dB;
	SINT16 gainIdx;
	SINT16 gain_dB;

}PHY_aagcCfg_s;

/*****************************************************************************/
/* Data Structures                                                           */
/*****************************************************************************/
typedef struct 
{
	UINT32 nsAcc[6];     // normalized acc ns for prv symbol
	UINT16 nbiCnt[6];    // nbi count for prv symb

}PHY_nve_t; 

#define PHY_NBI_THOLD                        30
#define PHY_SYNC_NBI_THOLD                   15

typedef enum
{
	PHY_NBI_HDR     = 0,
	PHY_NBI_PAYLOAD = 1,
	PHY_NBI_PRMB    = 2

}PHY_nbiMode_t;

typedef struct
{
	Uint16 *pnScm_p; //pointer to the PN sequence for scrambler; reload every PPDU
}PHY_descm_handle_t;

typedef struct
{
	ComplexShort u[96];       /* Hard decisons */
	int16 *gama_p;
}PHY_eqz_data_t;

extern PHY_afeBuf_t PHY_afeBuf_s;


PRIME_status_t FSM_event(FSM_stateMachine_t *fsm_p, UINT16 event, void *data_p);

uint16 getCRC8 (uint16 input_crc8_accum, uint16 * msg, parity_t parity, uint16 rxLen);

void PHY_cfft16(PHY_cfft16_t *fft_hnd);
void PHY_cfft16_brev(PHY_cfft16_t *fft_hnd);
void PHY_cfft16_init(void *data_p);
void PHY_cfft16_calc(void *data_p);
void PHY_firInit(PHY_fir_t *fir_p, const SINT16  *coeff_p, UINT16 nTaps);
void PHY_cfft16_128p_init(PHY_cfft16_t *fft_p, ComplexShort *in_p);
void PHY_cifft16(PHY_cfft16_t *fft_hnd);

SINT16 UTIL_blockShortMean(UINT16 nSampsInLog2, SINT16 *in_p);
void UTIL_blockShortOffset(UINT16 nSize, SINT16 *data_p, SINT16 val);
void UTIL_blockShortCopy(UINT16 nSize, SINT16 *src_p, SINT16 *dst_p);
void UTIL_blockShortFill(UINT16 nSize, SINT16 *dst_p, SINT16 val);
void UTIL_blockLongFill(UINT16 nSize, SINT32 *dst_p, SINT32 val);
long UTIL_blockShortComplexPower(UINT16 nSamps, SINT16 *in_p);
void UTIL_blockLongCopy(UINT16 nSize, SINT32 *src_p, SINT32 *dst_p);
void UTIL_blockPack2Word(UINT16 nBits, UINT16 offset, UINT16 *in_p, UINT16 *out_p);
void UTIL_blockShortComplexSat(UINT16 nSize, SINT16 *data_p, SINT16 maxVal, SINT16 minVal);
void UTIL_ShortComplexConjMult(UINT16 nSize, ComplexShort *src_p, const ComplexShort *m_p, ComplexShort *dst_p, UINT16 shift);
void UTIL_ShortComplexDotProduct(UINT16 nSize, ComplexShort *src_p, ComplexShort *m_p, ComplexShort *result_p, UINT16 shift);
void UTIL_blockCmplxShortCopy(UINT16 nSize, SINT32 *src_p, SINT32 *dst_p);
void UTIL_blockShortComplexMult(UINT16 nSize, ComplexShort *src_p, const ComplexShort *m_p, ComplexShort *dst_p, UINT16 shift);
void UTIL_blockUnpack2Bits(UINT16 nSize, UINT16 *in_p, UINT16 *out_p);
long UTIL_blockShortPower(UINT16 nSamps, SINT16 *in_p);
void UTIL_blockLongCircularCopy(UINT16 nSize, SINT32 *src_p, SINT32 *dst_p, UINT16 bufSize);

SINT32 MATH_Q0linearToQ4dB(SINT32 value);
UINT32 MATH_divide32_16_q15(UINT32 num, UINT16 den);
SINT32 MATH_Q4dBToQ12linear(UINT32 x);
SINT32 __IQsat(SINT32 llrTmp, SINT32 max, SINT32 min);

void PHY_eqz_genHdr(ComplexShort *y_p, int16 *gama_p);
void PHY_eqz_genPld_llr(UINT16 *sigma2_inv_p, int16 *llr_p, Uint16 mod);
void PHY_eqz_genPld(ComplexShort *y_p, int16 *gama_p, Uint16 mod);
void PHY_eqz_genHdr_llr(UINT16 *sigma2_inv_p, int16 *llr_p);

void PHY_dtlv(UINT16 nBits, SINT16 *in_p, SINT16 *out_p, UINT16 idx);
void PHY_intlv(UINT16 nBits, UINT16 *in_p, UINT16 *out_p, UINT16 idx);
void PHY_dtlvBlk(UINT16 nBits, SINT16 *in_p, SINT16 *out_p, UINT16 idx);
void PHY_intlvBlk(UINT16 nBits, UINT16 *in_p, UINT16 *out_p, UINT16 idx);

void PHY_mod_pnLoad();
void PHY_mod_genPld(Uint16 *b_p, ComplexShort *x_p, Uint16 mod);
void PHY_mod_genHdr(Uint16 *b_p, ComplexShort *x_p);

void PHY_scm_pnLoad();
void PHY_descm_pnLoad();
void PHY_scm(Uint16 *b_p, Uint16 *x_p, Uint16 length);
PRIME_status_t PHY_descm(int16 *in_p, Buffer_t *bd_p, Uint16 numSoftBits);

void PHY_cnvDecInit(int nBits);
void PHY_cnvDec(UINT16 bit_in, SINT16 *in_p, UINT16 *out_p, int flag);
void PHY_cnvDecMetricRescale(void);
void PHY_cnvEncInit(PHY_cnvEnc_t *cnvEnc_p);
void PHY_cnvEnc(PHY_cnvEnc_t *cnvEnc_p);

void PHY_aagcInit(PHY_aagc_t *aagc_p, PHY_aagcStage_t stage);
void PHY_aagcSet(PHY_aagcMode_t mode, SINT16 idx, PHY_aagc_t *aagc_p);
void PHY_aagcMeasure(UINT32 aagcPower, ComplexShort *dfe_p, PHY_aagc_t *aagc_p);
void PHY_dagc(SINT16 nSamps, ComplexShort *in_p, PHY_dagc_t *dagc_p);
void PHY_aagcUpdateMeas(PHY_aagc_t *aagc_p);
void PHY_aagcUpdateGain(PHY_aagc_t *aagc_p);
void PHY_firPReImInDn4(UINT16 nSamps, PHY_fir_t *fir_p, SINT16 *in_p, ComplexShort *out_p);
void PHY_firCplxInUp8Cvt(UINT16 nSamps, PHY_fir_t *fir_p, SINT16 *in_p, SINT16 *out_p); 

void PHY_flexCfg(UINT16 startIdx);
SINT32 MATH_blockCosSin (SINT16 N, SINT32 angle, SINT32 delta, ComplexShort *dst_p);

#endif //_PHY_H